//
//  OTCameraCapture.m
//  OldTime
//
//  Created by 茶 on 2023/10/25.
//

#import "CACameraCapture.h"
#import <AVFoundation/AVFoundation.h>
#import <Metal/Metal.h>
#import <MetalKit/MetalKit.h>
#import "CACameraUtil.h"

@interface CACameraCapture () <AVCapturePhotoCaptureDelegate, AVCaptureVideoDataOutputSampleBufferDelegate>

@property (strong, nonatomic) AVCaptureDevice* device;
@property (strong, nonatomic) AVCaptureSession* captureSession;
@property (nonatomic, strong) AVCaptureDeviceInput *input;
@property (nonatomic, strong) AVCaptureVideoDataOutput* output;
@property (strong, nonatomic) UIImage* cameraImage;

@end

@implementation CACameraCapture

- (instancetype)initCamera{
    self = [super init];
    if (self) {
        _queue = dispatch_queue_create("cameraQueue", NULL);
        AVAuthorizationStatus status = [AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeVideo];
        if (status == AVAuthorizationStatusAuthorized) {
            [self setup];
        } else {
            CAWeakify(self);
            [AVCaptureDevice requestAccessForMediaType:AVMediaTypeVideo completionHandler:^(BOOL granted) {
                CAStrongify(self);
                [self setup];
            }];
        }
    }
    return self;
}

- (void)setup {
    _device = [CACameraUtil videoCaptureDeviceWithPosition:AVCaptureDevicePositionBack];
    
    _input = [AVCaptureDeviceInput deviceInputWithDevice:self.device error:nil];
    AVCaptureVideoDataOutput* output = [[AVCaptureVideoDataOutput alloc] init];
    output.alwaysDiscardsLateVideoFrames = YES;
    
    
    NSString* key = (NSString *) kCVPixelBufferPixelFormatTypeKey;
    NSNumber* value = [NSNumber numberWithUnsignedInt:kCVPixelFormatType_32BGRA];
    NSDictionary* videoSettings = [NSDictionary dictionaryWithObject:value forKey:key];
    [output setVideoSettings:videoSettings];
    output.alwaysDiscardsLateVideoFrames = YES;
    [output setSampleBufferDelegate:self queue:_queue];
    _output = output;
    
    self.captureSession = [[AVCaptureSession alloc] init];
    if ([self.captureSession canAddInput:_input]) {
        [self.captureSession addInput:_input];
    }
    if ([self.captureSession canAddOutput:output]) {
        [self.captureSession addOutput:output];
    }
    [self.captureSession setSessionPreset:AVCaptureSessionPreset640x480];

    AVCaptureConnection *videoConnection = [self connectionWithMediaType:AVMediaTypeVideo fromConnections:[output connections]];
    if ([videoConnection isVideoOrientationSupported]) {
        [videoConnection setVideoOrientation:AVCaptureVideoOrientationPortraitUpsideDown];
        [videoConnection setVideoMirrored:YES];
    }
    [self startRunning];
}

- (void)startRunning {
    dispatch_async(_queue, ^{
        if (![self.captureSession isRunning]) {
            [self.captureSession startRunning];
        }
    });
}

- (void)stopRunning {
    dispatch_async(_queue, ^{
        [self.captureSession stopRunning];
    });
}

- (UIImage *)takePhoto {
    
    return self.cameraImage;
}

- (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection *)connection {
    CVPixelBufferRef pixelBuffer = CMSampleBufferGetImageBuffer(sampleBuffer);
    if (pixelBuffer) {
        if ([_delegate respondsToSelector:@selector(camera:processFrame:)]) {
            [_delegate camera:self processFrame:pixelBuffer];
        }
    } else {
        NSLog(@"captureOutput:didOutput 读取失败");
    }
}

- (AVCaptureConnection *)connectionWithMediaType:(NSString *)mediaType fromConnections:(NSArray *)connections {
    for ( AVCaptureConnection *connection in connections ) {
        for ( AVCaptureInputPort *port in [connection inputPorts] ) {
            if ( [[port mediaType] isEqual:mediaType] ) {
                return connection;
            }
        }
    }
    return nil;
}

- (void)setIsFront:(BOOL)isFront {
    _isFront = isFront;
    [_captureSession removeInput:_input];
    _device = nil;
    if (isFront) {
        _device = [CACameraUtil videoCaptureDeviceWithPosition:AVCaptureDevicePositionFront];
        _input = [AVCaptureDeviceInput deviceInputWithDevice:self.device error:nil];
        [_captureSession addInput:_input];
        AVCaptureConnection *videoConnection = [self connectionWithMediaType:AVMediaTypeVideo fromConnections:[_output connections]];
        if ([videoConnection isVideoOrientationSupported]) {
            [videoConnection setVideoOrientation:AVCaptureVideoOrientationPortraitUpsideDown];
            [videoConnection setVideoMirrored:NO];
        }
    } else {
        _device = [CACameraUtil videoCaptureDeviceWithPosition:AVCaptureDevicePositionBack];
        _input = [AVCaptureDeviceInput deviceInputWithDevice:self.device error:nil];
        [_captureSession addInput:_input];
        AVCaptureConnection *videoConnection = [self connectionWithMediaType:AVMediaTypeVideo fromConnections:[_output connections]];
        if ([videoConnection isVideoOrientationSupported]) {
            [videoConnection setVideoOrientation:AVCaptureVideoOrientationPortraitUpsideDown];
            [videoConnection setVideoMirrored:YES];
        }
    }
    
    
}



@end


